#ifndef __OBJECT_OBJ_FN_H__

#define __OBJECT_OBJ_FN_H__

#include "utils.h"
#include "meta_obj.h"

typedef struct {
    char *fnName; // 函数名
    IntBuffer lineNo;// 行号
} FnDebug; // 在函数中的调试结构

typedef struct {
    ObjHeader objHeader;  // 对象头
    ByteBuffer instrStream; // 函数编译后的指令流
    /**
     * 当ObjFn表示函数时此变量无效
     */
    ValueBuffer constants;

    ObjModule *module; // 本函数所属模块

    uint32_t maxStackSlotUsedNum;  // 运行时栈
    /**
     * 本函数所引用的upvalue的数量，upvalue是位于本函数直接或间接外层函数中的局部变量，也就是自由变量的数量
     */
    uint32_t upvalueNum; // 本函数所涵盖的upvalue
    uint8_t argNum; // 函数期望的参数个数
#if DEBUG
    FnDebug debug;
#endif
} ObjFn;  // 函数对象

typedef struct upvalue {
    ObjHeader objHeader;

    // 指向所关联的upvalue，局部变量肯定位于栈中，因此提出用变量localVarPtr指向栈中的upvalue以供引用该upvalue的内层函数使用
    // 当外层函数的运行时栈被释放了的时候
    // upvalue会从栈中被复制到closedUpvalue
    // 使得localVarPtr指向closedUpvalue的地址
    Value *localVarPtr;

    Value closedUpvalue;  // 已被关闭的upvalue

    struct upvalue *next; // 用以链接openUpvalue链表，默认是openUpvalue
} ObjUpvalue;  // upvalue对象

typedef struct {
    ObjHeader objHeader;
    ObjFn *fn; // 闭包中所要引用的函数

    ObjUpvalue *upvalues[0]; // 用以存储该函数的closed upvalue
} ObjClosure;  // 闭包对象

typedef struct {
    uint8_t *ip;  // 程序计数器，指向下一个将被指向的指令

    ObjClosure *closure; // 在本frame中执行的闭包函数

    // 此项用于指向frame所在thread运行时栈的起始地址
    Value *stackStart;  // frame是共享thread.stack

} Frame;  // 调用框架

#define INITIAL_FRAME_NUM 4

ObjUpvalue* newObjUpvalue(VM *vm, Value *localVarPtr);
ObjClosure* newObjClosure(VM *vm, ObjFn *objFn);
ObjFn* newObjFn(VM *vm, ObjModule *objModule, uint32_t maxStackSlotUsedNum);

#endif